home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS / antlr / gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-14  |  48.2 KB  |  1,996 lines  |  [TEXT/MPS ]

  1. /*
  2.  * gen.c
  3.  *
  4.  * $Id: gen.c,v 1.10 1994/08/29 20:16:14 parrt Exp parrt $
  5.  * $Revision: 1.10 $
  6.  *
  7.  * Generate C code (ANSI, K&R, C++)
  8.  *
  9.  * SOFTWARE RIGHTS
  10.  *
  11.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  12.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  13.  * company may do whatever they wish with source code distributed with
  14.  * PCCTS or the code generated by PCCTS, including the incorporation of
  15.  * PCCTS, or its output, into commerical software.
  16.  * 
  17.  * We encourage users to develop software with PCCTS.  However, we do ask
  18.  * that credit is given to us for developing PCCTS.  By "credit",
  19.  * we mean that if you incorporate our source code into one of your
  20.  * programs (commercial product, research project, or otherwise) that you
  21.  * acknowledge this fact somewhere in the documentation, research report,
  22.  * etc...  If you like PCCTS and have developed a nice tool with the
  23.  * output, please mention that you developed it using PCCTS.  In
  24.  * addition, we ask that this header remain intact in our source code.
  25.  * As long as these guidelines are kept, we expect to continue enhancing
  26.  * this system and expect to make other tools available as they are
  27.  * completed.
  28.  *
  29.  * ANTLR 1.23
  30.  * Terence Parr
  31.  * Parr Research Corporation
  32.  * with Purdue University and AHPCRC, University of Minnesota
  33.  * 1989-1994
  34.  */
  35. #include <stdio.h>
  36. #ifdef __cplusplus
  37. #ifndef __STDC__
  38. #define __STDC__
  39. #endif
  40. #endif
  41. #include <ctype.h>
  42. #include "set.h"
  43. #include "syn.h"
  44. #include "hash.h"
  45. #include "generic.h"
  46. #include "dlgdef.h"
  47.  
  48. #define NumExprPerLine    4
  49. static     int on1line=0;
  50.  
  51.                     /* T r a n s l a t i o n  T a b l e s */
  52.  
  53. /* C_Trans[node type] == pointer to function that knows how to translate that node. */
  54. #ifdef __cplusplus
  55. void (*C_Trans[NumNodeTypes+1])(...) = {
  56.     NULL,
  57.     NULL,                    /* See next table.  Junctions have many types */
  58.     (void (*)(...)) genRuleRef,
  59.     (void (*)(...)) genToken,
  60.     (void (*)(...)) genAction
  61. };
  62. #else
  63. void (*C_Trans[NumNodeTypes+1])() = {
  64.     NULL,
  65.     NULL,                    /* See next table.  Junctions have many types */
  66.     genRuleRef,
  67.     genToken,
  68.     genAction
  69. };
  70. #endif
  71.  
  72. /* C_JTrans[Junction type] == pointer to function that knows how to translate that
  73.  * kind of junction node.
  74.  */
  75. #ifdef __cplusplus
  76. void (*C_JTrans[NumJuncTypes+1])(...) = {
  77.     NULL,
  78.     (void (*)(...)) genSubBlk,
  79.     (void (*)(...)) genOptBlk,
  80.     (void (*)(...)) genLoopBlk,
  81.     (void (*)(...)) genEndBlk,
  82.     (void (*)(...)) genRule,
  83.     (void (*)(...)) genJunction,
  84.     (void (*)(...)) genEndRule,
  85.     (void (*)(...)) genPlusBlk,
  86.     (void (*)(...)) genLoopBegin
  87. };
  88. #else
  89. void (*C_JTrans[NumJuncTypes+1])() = {
  90.     NULL,
  91.     genSubBlk,
  92.     genOptBlk,
  93.     genLoopBlk,
  94.     genEndBlk,
  95.     genRule,
  96.     genJunction,
  97.     genEndRule,
  98.     genPlusBlk,
  99.     genLoopBegin
  100. };
  101. #endif
  102.  
  103. #define PastWhiteSpace(s)    while (*(s) == ' ' || *(s) == '\t') {s++;}
  104.  
  105. static int tabs = 0;
  106. #define TAB { int i; for (i=0; i<tabs; i++) fputc('\t', output); }
  107. static void
  108. #ifdef __STDC__
  109. tab( void )
  110. #else
  111. tab( )
  112. #endif
  113. TAB
  114.  
  115. #ifdef __STDC__
  116. static ActionNode *findImmedAction( Node * );
  117. static void dumpRetValAssign(char *, char *);
  118. static void dumpAfterActions(FILE *output);
  119. static set ComputeErrorSet(Junction *, int);
  120. static void makeErrorClause(Junction *, set, int);
  121. static void DumpFuncHeader( Junction *, RuleEntry * );
  122. static int has_guess_block_as_first_item(Junction *);
  123. static int genExprSets(set *, int);
  124. static void genExprTree( Tree *t, int k );
  125. #else
  126. static ActionNode *findImmedAction();
  127. static void dumpRetValAssign();
  128. static void dumpAfterActions();
  129. static set ComputeErrorSet();
  130. static void makeErrorClause();
  131. static void DumpFuncHeader();
  132. static int has_guess_block_as_first_item();
  133. static int genExprSets();
  134. static void genExprTree();
  135. #endif
  136.  
  137. #define gen(s)            {tab(); fprintf(output, s);}
  138. #define gen1(s,a)        {tab(); fprintf(output, s,a);}
  139. #define gen2(s,a,b)        {tab(); fprintf(output, s,a,b);}
  140. #define gen3(s,a,b,c)    {tab(); fprintf(output, s,a,b,c);}
  141. #define gen4(s,a,b,c,d)    {tab(); fprintf(output, s,a,b,c,d);}
  142. #define gen5(s,a,b,c,d,e)    {tab(); fprintf(output, s,a,b,c,d,e);}
  143. #define gen6(s,a,b,c,d,e,f)    {tab(); fprintf(output, s,a,b,c,d,e,f);}
  144.  
  145. #define _gen(s)            {fprintf(output, s);}
  146. #define _gen1(s,a)        {fprintf(output, s,a);}
  147. #define _gen2(s,a,b)    {fprintf(output, s,a,b);}
  148. #define _gen3(s,a,b,c)    {fprintf(output, s,a,b,c);}
  149. #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
  150. #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
  151. #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
  152.  
  153. static void
  154. #ifdef __STDC__
  155. warn_about_using_gk_option(void)
  156. #else
  157. warn_about_using_gk_option()
  158. #endif
  159. {
  160.     static int warned_already=0;
  161.  
  162.     if ( !DemandLookahead || warned_already ) return;
  163.     warned_already = 1;
  164.     warnNoFL("-gk option could cause trouble for <<...>>? predicates");
  165. }
  166.  
  167. void
  168. #ifdef __STDC__
  169. freeBlkFsets( Junction *q )
  170. #else
  171. freeBlkFsets( q )
  172. Junction *q;
  173. #endif
  174. {
  175.     int i;
  176.     Junction *alt;
  177.     require(q!=NULL, "freeBlkFsets: invalid node");
  178.  
  179.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  180.     {
  181.         for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
  182.     }
  183. }
  184.  
  185. /*
  186.  * Generate a local variable allocation for each token references
  187.  * in this block.
  188.  */
  189. static void
  190. #ifdef __STDC__
  191. genTokenPointers( Junction *q )
  192. #else
  193. genTokenPointers( q )
  194. Junction *q;
  195. #endif
  196. {
  197.     /* Rule refs are counted and can be referenced, but their
  198.      * value is not set to anything useful ever.
  199.      *
  200.      * The ptrs are to be named _tij where i is the current level
  201.      * and j is the element number within an alternative.
  202.      */
  203.     int first=1, t;
  204.     set a;
  205.  
  206.     if ( set_deg(q->tokrefs) == 0 ) return;
  207.     a = set_dup(q->tokrefs);
  208.     gen("ANTLRToken ");
  209.     for (; !set_nil(a); set_rm(t, a))
  210.     {
  211.         t = set_int(a);
  212.         if ( first ) first = 0;
  213.         else _gen(",");
  214.         if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
  215.         _gen2("*_t%d%d", BlkLevel, t);
  216.         if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
  217.         else _gen("=NULL");
  218.     }
  219.     _gen(";\n");
  220.     set_free(a);
  221. }
  222.  
  223. /*
  224.  * Generate a local variable allocation for each token or rule reference
  225.  * in this block.
  226.  */
  227. static void
  228. #ifdef __STDC__
  229. genASTPointers( Junction *q )
  230. #else
  231. genASTPointers( q )
  232. Junction *q;
  233. #endif
  234. {
  235.     int first=1, t;
  236.     set a;
  237.  
  238.     a = set_or(q->tokrefs, q->rulerefs);
  239.     if ( set_deg(a) > 0 )
  240.     {
  241.         gen("AST ");
  242.         for (; !set_nil(a); set_rm(t, a))
  243.         {
  244.             t = set_int(a);
  245.             if ( first ) first = 0;
  246.             else _gen(",");
  247.             _gen2("*_ast%d%d=NULL", BlkLevel, t);
  248.         }
  249.         set_free(a);
  250.     }
  251.     _gen(";\n");
  252. }
  253.  
  254. static void
  255. #ifdef __STDC__
  256. BLOCK_Head( void )
  257. #else
  258. BLOCK_Head( )
  259. #endif
  260. {
  261.     gen("{\n");
  262.     tabs++;
  263.     if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
  264. }
  265.  
  266. static void
  267. #ifdef __STDC__
  268. BLOCK_Tail( void )
  269. #else
  270. BLOCK_Tail( )
  271. #endif
  272. {
  273.     if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
  274.     if ( !GenCC ) gen("}\n");
  275.     tabs--;
  276.     gen("}\n");
  277. }
  278.  
  279. static void
  280. #ifdef __STDC__
  281. BLOCK_Preamble( Junction *q )
  282. #else
  283. BLOCK_Preamble( q )
  284. Junction *q;
  285. #endif
  286. {
  287.     ActionNode *a;
  288.     Junction *begin;
  289.  
  290.     BLOCK_Head();
  291.     if ( GenCC ) genTokenPointers(q);
  292.     if ( GenCC&&GenAST ) genASTPointers(q);
  293.     if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
  294.     if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
  295.     else if ( !GenCC ) gen("zzMake0;\n");
  296.     if ( !GenCC ) gen("{\n");
  297.     if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
  298.     else begin = q;
  299.     if ( has_guess_block_as_first_item(begin) )
  300.     {
  301.         gen("zzGUESS_BLOCK\n");
  302.     }
  303.     if ( q->jtype == aLoopBegin )
  304.         a = findImmedAction( ((Junction *)q->p1)->p1 );    /* look at aLoopBlk */
  305.     else
  306.         a = findImmedAction( q->p1 );
  307.     if ( a!=NULL && !a->is_predicate ) {
  308.         dumpAction(a->action, output, tabs, a->file, a->line, 1);
  309.         a->done = 1;    /* remove action. We have already handled it */
  310.     }
  311. }
  312.  
  313. /* If predicates are allowed in parsing expressions:
  314.  *
  315.  * (    production 1
  316.  * |    production 2
  317.  * ...
  318.  * |    production n
  319.  * )
  320.  *
  321.  * where production 1 yields visible predicates: <<pred>>? <<pred2>>?
  322.  *
  323.  * generates (if -prc on):
  324.  *
  325.  * if ( (production 1 prediction) &&
  326.  *        (context_of_pred && pred) &&
  327.  *        (context_of_pred2 && pred2) ) {
  328.  *         ...
  329.  * }
  330.  * else if ( production 2 prediction ) {
  331.  *         ...
  332.  * }
  333.  * ...
  334.  *
  335.  *        p1
  336.  *        |
  337.  *        p2--p3
  338.  *
  339.  * results in
  340.  *
  341.  * if ( (production 1 prediction) &&
  342.  *        (context_of_p1 && p1) &&
  343.  *        ((context_of_p2 && p2)||
  344.  *        (context_of_p3 && p3)) &&
  345.  *        ) {
  346.  *         ...
  347.  * }
  348.  *
  349.  * If no context, then just test expression.
  350.  */
  351. void
  352. #ifdef __STDC__
  353. genPredTree( Predicate *p, Junction *j )
  354. #else
  355. genPredTree( p, j )
  356. Predicate *p;
  357. Junction *j;
  358. #endif
  359. {
  360.     int context_was_present = 0;
  361.  
  362.     _gen("(");
  363.     for (; p!=NULL; p=p->right)
  364.     {
  365.         if ( HoistPredicateContext )
  366.         {
  367.             context_was_present = 0;
  368.             if ( LL_k>1 && p->tcontext!=NULL )
  369.             {
  370.                 context_was_present = 1;
  371.                 _gen("((");
  372.                 genExprTree(p->tcontext, 1);
  373.                 _gen(") ? ");
  374.             }
  375.             else if ( LL_k==1 && set_deg(p->scontext[1])>0 )
  376.             {
  377.                 context_was_present = 1;
  378.                 _gen("((");
  379.                 genExprSets(&(p->scontext[0]), CLL_k);
  380.                 _gen(") ? ");
  381.             }
  382.         }
  383.  
  384.         _gen("(");
  385.         dumpAction(p->expr, output, 0, j->file, j->line, 0);
  386.         _gen(")");
  387.  
  388.         if ( HoistPredicateContext && context_was_present ) _gen(" : 1)");
  389.  
  390.         if ( p->down!=NULL )
  391.         {
  392.             _gen("&&");
  393.             genPredTree(p->down, j);
  394.         }
  395.  
  396.         if ( p->right!=NULL ) _gen("||");
  397.     }
  398.     _gen(")");
  399. }
  400.  
  401. static void
  402. #ifdef __STDC__
  403. genExprTree( Tree *t, int k )
  404. #else
  405. genExprTree( t, k )
  406. Tree *t;
  407. int k;
  408. #endif
  409. {
  410.     require(t!=NULL, "genExprTree: NULL tree");
  411.     
  412.     if ( t->token == ALT )
  413.     {
  414.         _gen("("); genExprTree(t->down, k); _gen(")");
  415.         if ( t->right!=NULL )
  416.         {
  417.             _gen("||");
  418.             on1line++;
  419.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  420.             _gen("("); genExprTree(t->right, k); _gen(")");
  421.         }
  422.         return;
  423.     }
  424.     if ( t->down!=NULL ) _gen("(");
  425.     _gen1("LA(%d)==",k);
  426.     if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
  427.     else _gen1("%s", TokenString(t->token));
  428.     if ( t->down!=NULL )
  429.     {
  430.         _gen("&&");
  431.         on1line++;
  432.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  433.         _gen("("); genExprTree(t->down, k+1); _gen(")");
  434.     }
  435.     if ( t->down!=NULL ) _gen(")");
  436.     if ( t->right!=NULL )
  437.     {
  438.         _gen("||");
  439.         on1line++;
  440.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  441.         _gen("("); genExprTree(t->right, k); _gen(")");
  442.     }
  443. }
  444.  
  445. /*
  446.  * Generate LL(k) type expressions of the form:
  447.  *
  448.  *         (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
  449.  *         (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
  450.  *            .....
  451.  *         (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
  452.  *
  453.  * If GenExprSets generate:
  454.  *
  455.  *        (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
  456.  *
  457.  * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
  458.  * set in fset <=CLL_k.
  459.  * k=1..CLL_k where CLL_k >= 1.
  460.  *
  461.  * This routine is visible only to this file and cannot answer a TRANS message.
  462.  *
  463.  */
  464. static int
  465. #ifdef __STDC__
  466. genExpr( Junction *j )
  467. #else
  468. genExpr( j )
  469. Junction *j;
  470. #endif
  471. {
  472.     int max_k;
  473.  
  474.     /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
  475.      * from CLL_k..LL_k
  476.      */
  477.     {
  478.         int limit;
  479.         if ( j->ftree!=NULL ) limit = LL_k;
  480.         else limit = CLL_k;
  481.         max_k = genExprSets(j->fset, limit);
  482.     }
  483.  
  484.     /* Do tests for real tuples from other productions that conflict with
  485.      * artificial tuples generated by compression (using sets of tokens
  486.      * rather than k-trees).
  487.      */
  488.     if ( j->ftree != NULL )
  489.     {
  490.         _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
  491.     }
  492.  
  493.     if ( ParseWithPredicates && j->predicate!=NULL )
  494.     {
  495.         Predicate *p = j->predicate;
  496.         warn_about_using_gk_option();
  497.         _gen("&&");
  498.         genPredTree(p, j);
  499.     }
  500.  
  501.     return max_k;
  502. }
  503.  
  504. static int
  505. #ifdef __STDC__
  506. genExprSets( set *fset, int limit )
  507. #else
  508. genExprSets( fset, limit )
  509. set *fset;
  510. int limit;
  511. #endif
  512. {
  513.     int k = 1;
  514.     int max_k = 0;
  515.     unsigned *e, *g, firstTime=1;
  516.  
  517.     if ( GenExprSets )
  518.     {
  519.         while ( !set_nil(fset[k]) && k<=limit )
  520.         {
  521.             if ( set_deg(fset[k])==1 )    /* too simple for a set? */
  522.             {
  523.                 int e;
  524.                 _gen1("(LA(%d)==",k);
  525.                 e = set_int(fset[k]);
  526.                 if ( TokenString(e) == NULL ) _gen1("%d)", e)
  527.                 else _gen1("%s)", TokenString(e));
  528.             }
  529.             else
  530.             {
  531.                 NewSet();
  532.                 FillSet( fset[k] );
  533.                 _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
  534.             }
  535.             if ( k>max_k ) max_k = k;
  536.             if ( k == CLL_k ) break;
  537.             k++;
  538.             if ( !set_nil(fset[k]) && k<=limit ) _gen(" && ");
  539.             on1line++;
  540.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  541.         }
  542.         return max_k;
  543.     }
  544.  
  545.     while ( !set_nil(fset[k]) && k<=limit )
  546.     {
  547.         if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
  548.         for (; *e!=nil; e++)
  549.         {
  550.             if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
  551.             on1line++;
  552.             if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  553.             _gen1("LA(%d)==",k);
  554.             if ( TokenString(*e) == NULL ) _gen1("%d", *e)
  555.             else _gen1("%s", TokenString(*e));
  556.         }
  557.         free( (char *)g );
  558.         _gen(")");
  559.         if ( k>max_k ) max_k = k;
  560.         if ( k == CLL_k ) break;
  561.         k++;
  562.         if ( !set_nil(fset[k]) && k<=limit ) { firstTime=1; _gen(" && "); }
  563.         on1line++;
  564.         if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
  565.     }
  566.     return max_k;
  567. }
  568.  
  569. /*
  570.  * Generate code for any type of block.  If the last alternative in the block is
  571.  * empty (not even an action) don't bother doing it.  This permits us to handle
  572.  * optional and loop blocks as well.
  573.  *
  574.  * Only do this block, return after completing the block.
  575.  * This routine is visible only to this file and cannot answer a TRANS message.
  576.  */
  577. static set
  578. #ifdef __STDC__
  579. genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
  580. #else
  581. genBlk( q, jtype, max_k, need_right_curly )
  582. Junction *q;
  583. int jtype;
  584. int *max_k;
  585. int *need_right_curly;
  586. #endif
  587. {
  588.     set f;
  589.     Junction *alt;
  590.     int a_guess_in_block = 0;
  591.     require(q!=NULL,                "genBlk: invalid node");
  592.     require(q->ntype == nJunction,    "genBlk: not junction");
  593.  
  594.     *need_right_curly=0;
  595.     if ( q->p2 == NULL )    /* only one alternative?  Then don't need if */
  596.     {    
  597.         if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
  598.         {
  599.             warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
  600.             gen("zzGUESS\n");    /* guess anyway to make output code consistent */
  601.             gen("if ( !zzrv )\n");
  602.         }
  603.         TRANS(q->p1);
  604.         return empty;        /* no decision to be made-->no error set */
  605.     }
  606.  
  607.     f = First(q, 1, jtype, max_k);
  608.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  609.     {
  610.         if ( alt->p2 == NULL )                    /* chk for empty alt */
  611.         {    
  612.             Node *p = alt->p1;
  613.             if ( p->ntype == nJunction )
  614.             {
  615.                 /* we have empty alt */
  616.                 if ( ((Junction *)p)->p1 == (Node *)q->end )
  617.                 {
  618.                     break;                        /* don't do this one, quit */
  619.                 }
  620.             }
  621.         }
  622.         if ( alt != q ) gen("else ")
  623.         else
  624.         {
  625.             if ( DemandLookahead )
  626.                 if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
  627.                 else gen1("look(%d);\n", *max_k);
  628.         }
  629.         if ( alt!=q )
  630.         {
  631.             _gen("{\n");
  632.             tabs++;
  633.             (*need_right_curly)++;
  634.             /* code to restore state if a prev alt didn't follow guess */
  635.             if ( a_guess_in_block )
  636.                    if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_DONE;\n");}
  637.                 else gen("if ( guessing ) zzGUESS_DONE;\n");
  638.         }
  639.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
  640.         {
  641.             a_guess_in_block = 1;
  642.             gen("zzGUESS\n");
  643.         }
  644.         gen("if ( ");
  645.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
  646.         genExpr(alt);
  647.         _gen(" ) ");
  648.         _gen("{\n");
  649.         tabs++;
  650.         TRANS(alt->p1);
  651.         --tabs;
  652.         gen("}\n");
  653.     }
  654.     return f;
  655. }
  656.  
  657. static int
  658. #ifdef __STDC__
  659. has_guess_block_as_first_item( Junction *q )
  660. #else
  661. has_guess_block_as_first_item( q )
  662. Junction *q;
  663. #endif
  664. {
  665.     Junction *alt;
  666.  
  667.     for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
  668.     {
  669.         if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
  670.     }
  671.     return 0;
  672. }
  673.  
  674. /* return NULL if 1st item of alt is (...)? block; else return ptr to aSubBlk node
  675.  * of (...)?;  This function ignores actions and predicates.
  676.  */
  677. Junction *
  678. #ifdef __STDC__
  679. first_item_is_guess_block( Junction *q )
  680. #else
  681. first_item_is_guess_block( q )
  682. Junction *q;
  683. #endif
  684. {
  685.     while ( q!=NULL && ((q->ntype==nJunction && q->jtype==Generic) || q->ntype==nAction) )
  686.     {
  687.         if ( q->ntype==nJunction ) q = (Junction *)q->p1;
  688.         else q = (Junction *) ((ActionNode *)q)->next;
  689.     }
  690.  
  691.     if ( q==NULL ) return NULL;
  692.     if ( q->ntype!=nJunction ) return NULL;
  693.     if ( q->jtype!=aSubBlk ) return NULL;
  694.     if ( !q->guess ) return NULL;
  695.     return q;
  696. }
  697.  
  698. /* Generate an action.  Don't if action is NULL which means that it was already
  699.  * handled as an init action.
  700.  */
  701. void
  702. #ifdef __STDC__
  703. genAction( ActionNode *p )
  704. #else
  705. genAction( p )
  706. ActionNode *p;
  707. #endif
  708. {
  709.     require(p!=NULL,            "genAction: invalid node and/or rule");
  710.     require(p->ntype==nAction,    "genAction: not action");
  711.     
  712.     if ( !p->done )
  713.     {
  714.         if ( p->is_predicate )
  715.         {
  716.             gen("if (!(");
  717.             /* make sure that '#line n' is on front of line */
  718.             if ( GenLineInfo && p->file != -1 ) _gen("\n");
  719.             dumpAction(p->action, output, 0, p->file, p->line, 0);
  720.             if ( p->pred_fail != NULL )
  721.             {
  722.                 _gen("))\n");
  723. /*                if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n");*/
  724.                 tabs++;
  725.                 gen1("%s;\n", p->pred_fail);
  726.                 tabs--;
  727. /*                if ( FoundGuessBlk ) gen("}\n");*/
  728.             }
  729.             else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",p->action);
  730.         }
  731.         else
  732.         {
  733.             if ( FoundGuessBlk )
  734.                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
  735.                 else gen("zzNON_GUESS_MODE {\n");
  736.             dumpAction(p->action, output, tabs, p->file, p->line, 1);
  737.             if ( FoundGuessBlk ) gen("}\n");
  738.         }
  739.     }
  740.     TRANS(p->next)
  741. }
  742.  
  743. /*
  744.  *        if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
  745.  *        else pass addr of temp root ptr (&_ast) (don't zzlink it in).
  746.  *
  747.  *        if ! modifies rule-ref, then never link it in and never pass zzSTR.
  748.  *        Always pass address of temp root ptr.
  749.  */
  750. void
  751. #ifdef __STDC__
  752. genRuleRef( RuleRefNode *p )
  753. #else
  754. genRuleRef( p )
  755. RuleRefNode *p;
  756. #endif
  757. {
  758.     Junction *q;
  759.     RuleEntry *r, *r2;
  760.     char *parm = "";
  761.     require(p!=NULL,            "genRuleRef: invalid node and/or rule");
  762.     require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
  763.     
  764.     r = (RuleEntry *) hash_get(Rname, p->text);
  765.     if ( r == NULL ) {warnFL( eMsg1("rule %s not defined", p->text), FileStr[p->file], p->line ); return;}
  766.     r2 = (RuleEntry *) hash_get(Rname, p->rname);
  767.     if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
  768.  
  769.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
  770.  
  771.     if ( FoundGuessBlk && p->assign!=NULL )
  772.         if ( GenCC ) {gen("if ( !guessing ) {\n");}
  773.         else gen("zzNON_GUESS_MODE {\n");
  774.  
  775.     tab();
  776.     if ( GenAST )
  777.     {
  778.         if ( GenCC ) {
  779. /*            if ( r2->noAST || p->astnode==ASTexclude )
  780. */
  781.             {
  782.                 _gen("_ast = NULL;\n");
  783.                 parm = "&_ast";
  784.             }
  785. /* we always want to set just a pointer now, then set correct pointer after
  786.  
  787.             else {
  788.                 _gen("_astp = (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
  789.                 parm = "_astp";
  790.             }
  791. */
  792.             tab();
  793.         }
  794.         else {
  795.             if ( r2->noAST || p->astnode==ASTexclude )
  796.             {
  797.                 _gen("_ast = NULL; ");
  798.                 parm = "&_ast";
  799.             }
  800.             else parm = "zzSTR";
  801.         }
  802.         if ( p->assign!=NULL )
  803.         {
  804.             if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
  805.             else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
  806.         }
  807.         _gen5("%s%s(%s%s%s);", RulePrefix,
  808.                                p->text,
  809.                                parm,
  810.                                (p->parms!=NULL)?",":"",
  811.                                (p->parms!=NULL)?p->parms:"");
  812.         if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
  813.         {
  814.             /* rule has a ! or element does */
  815.             /* still need to assign to #i so we can play with it */
  816.             _gen("\n");
  817.             gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
  818.         }
  819.         else if ( !r2->noAST && p->astnode == ASTinclude )
  820.         {
  821.             /* rule doesn't have a ! and neither does element */
  822.             if ( GenCC ) {
  823.                 _gen("\n");
  824.                 gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
  825.                 gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
  826.                 tab();
  827.             }
  828.             else _gen(" ");
  829.             if ( GenCC ) {_gen("ASTBase::");} else _gen("zz");
  830.             _gen("link(_root, &_sibling, &_tail);");
  831.         }
  832.     }
  833.     else
  834.     {
  835.         if ( p->assign!=NULL )
  836.         {
  837.             if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
  838.             else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
  839.         }
  840.         _gen3("%s%s(%s);", RulePrefix, p->text, (p->parms!=NULL)?p->parms:"");
  841.         if ( p->assign!=NULL ) _gen("\n");
  842.     }
  843.     q = RulePtr[r->rulenum];    /* find definition of ref'd rule */
  844.     if ( p->assign!=NULL ) {
  845.         if ( HasComma(p->assign) )
  846.         {
  847.             _gen("\n");
  848.             dumpRetValAssign(p->assign, q->ret);
  849.             _gen("}");
  850.         }
  851.     }
  852.     _gen("\n");
  853.     if ( FoundGuessBlk && p->assign!=NULL ) {
  854.         gen("} else {\n");
  855.         gen5("%s%s(%s%s%s);\n", RulePrefix,
  856.                                p->text,
  857.                                parm,
  858.                                (p->parms!=NULL && *parm!='\0')?",":"",
  859.                                (p->parms!=NULL)?p->parms:"");
  860.         gen("}\n");
  861.     }
  862.     TRANS(p->next)
  863. }
  864.  
  865. /*
  866.  * Generate code to match a token.
  867.  *
  868.  * Getting the next token is tricky.  We want to ensure that any action
  869.  * following a token is executed before the next GetToken();
  870.  */ 
  871. void
  872. #ifdef __STDC__
  873. genToken( TokNode *p )
  874. #else
  875. genToken( p )
  876. TokNode *p;
  877. #endif
  878. {
  879.     RuleEntry *r;
  880.     ActionNode *a;
  881.     require(p!=NULL,            "genToken: invalid node and/or rule");
  882.     require(p->ntype==nToken,    "genToken: not token");
  883.     
  884.     r = (RuleEntry *) hash_get(Rname, p->rname);
  885.     if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
  886.  
  887.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, p->line, FileStr[p->file]);
  888.  
  889.     if ( !set_nil(p->tset) )
  890.     {
  891.         unsigned e;
  892.         set b;
  893.         b = set_dup(p->tset);
  894.         e = DefErrSet(&b, 0);
  895.         if ( GenCC ) {gen1("setmatch(err%d);", e);}
  896.         else gen1("zzsetmatch(zzerr%d);", e);
  897.         set_free(b);
  898.     }
  899.     else if ( TokenString(p->token)!=NULL )
  900.         gen1("zzmatch(%s);", TokenString(p->token))
  901.     else
  902.         gen1("zzmatch(%d);", p->token);
  903.  
  904.     a = findImmedAction( p->next );
  905.     /* generate the token copies */
  906.     if ( GenCC && p->elnum>0 )
  907.     {
  908.         if ( !DontCopyTokens ) {_gen2(" *_t%d%d = *((ANTLRToken *)LT(1));", BlkLevel-1, p->elnum);}
  909.         else _gen2(" _t%d%d = (ANTLRToken *)LT(1);", BlkLevel-1, p->elnum);
  910.         if ( LL_k>1 ) _gen(" labase++;");
  911.         _gen("\n");
  912.         tab();
  913.     }
  914.     if ( GenAST )
  915.     {
  916.         if ( FoundGuessBlk && p->astnode != ASTexclude )
  917.         {
  918.             if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
  919.             else {_gen("zzNON_GUESS_MODE {\n"); tab();}
  920.         }
  921.         if ( !r->noAST )
  922.         {
  923.             if ( GenCC && p->astnode != ASTexclude ) {
  924.                 _gen("\n");
  925.                 gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
  926.                 tab();
  927.             }
  928.             if ( GenCC && p->astnode != ASTexclude ) {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
  929.             else _gen(" ");
  930.             if ( p->astnode==ASTchild ) {
  931.                 if ( !GenCC ) _gen("zz");
  932.                 _gen("subchild(_root, &_sibling, &_tail);");
  933.             }
  934.             else if ( p->astnode==ASTroot ) {
  935.                 if ( !GenCC ) _gen("zz");
  936.                 _gen("subroot(_root, &_sibling, &_tail);");
  937.             }
  938.             if ( GenCC && p->astnode != ASTexclude ) {
  939.                 _gen("\n");
  940.                 tab();
  941.             }
  942.         }
  943.         else if ( !GenCC ) _gen(" zzastDPush;");
  944.         if ( FoundGuessBlk && p->astnode != ASTexclude )
  945.             {_gen("}\n"); tab();}
  946.     }
  947.     if ( a != NULL )
  948.     {
  949.         /* delay next token fetch until after action */
  950.         _gen("\n");
  951.         if ( a->is_predicate )
  952.         {
  953.             gen("if (!(");
  954.             dumpAction(a->action, output, 0, a->file, a->line, 0);
  955.             if ( a->pred_fail != NULL )
  956.             {
  957.                 _gen("))\n");
  958. /*                if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n");*/
  959.                 tabs++;
  960.                 gen1("%s;\n", a->pred_fail);
  961.                 tabs--;
  962. /*                if ( FoundGuessBlk ) gen("}\n");*/
  963.             }
  964.             else _gen1(")) {zzfailed_pred((ANTLRChar *)\"%s\");}\n",a->action);
  965.         }
  966.         else
  967.         {
  968.             if ( FoundGuessBlk )
  969.                 if ( GenCC ) {gen("if ( !guessing ) {\n");}
  970.                 else gen("zzNON_GUESS_MODE {\n");
  971.             dumpAction(a->action, output, tabs, a->file, a->line, 1);
  972.             if ( FoundGuessBlk ) gen("}\n");
  973.         }
  974.         a->done = 1;
  975.         if ( !DemandLookahead ) {
  976.             if ( GenCC ) gen(" consume();\n")
  977.             else _gen(" zzCONSUME;\n");
  978.         }
  979.         else gen("\n");
  980.         TRANS( a->next );
  981.     }
  982.     else
  983.     {
  984.         if ( !DemandLookahead ) {
  985.             if ( GenCC ) _gen(" consume();\n")
  986.             else _gen(" zzCONSUME;\n");
  987.         }
  988.         else _gen("\n");
  989.         TRANS(p->next);
  990.     }
  991. }
  992.  
  993. void
  994. #ifdef __STDC__
  995. genOptBlk( Junction *q )
  996. #else
  997. genOptBlk( q )
  998. Junction *q;
  999. #endif
  1000. {
  1001.     int max_k;
  1002.     set f;
  1003.     int need_right_curly;
  1004.     require(q!=NULL,                "genOptBlk: invalid node and/or rule");
  1005.     require(q->ntype == nJunction,    "genOptBlk: not junction");
  1006.     require(q->jtype == aOptBlk,    "genOptBlk: not optional block");
  1007.  
  1008.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1009.     BLOCK_Preamble(q);
  1010.     BlkLevel++;
  1011.     f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
  1012.     set_free(f);
  1013.     freeBlkFsets(q);
  1014.     BlkLevel--;
  1015.     if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
  1016.     {
  1017.         if ( !GenCC ) {gen("else if ( zzguessing ) zzGUESS_DONE;\n");}
  1018.         else gen("else if ( guessing ) zzGUESS_DONE;\n");
  1019.     }
  1020.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1021.     BLOCK_Tail();
  1022.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1023. }
  1024.  
  1025. /*
  1026.  * Generate code for a loop blk of form:
  1027.  *
  1028.  *                 |---|
  1029.  *                 v   |
  1030.  *               --o-G-o-->o--
  1031.  */
  1032. void
  1033. #ifdef __STDC__
  1034. genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
  1035. #else
  1036. genLoopBlk( begin, q, start, max_k )
  1037. Junction *begin;
  1038. Junction *q;
  1039. Junction *start;    /* where to start generating code from */
  1040. int max_k;
  1041. #endif
  1042. {
  1043.     set f;
  1044.     int need_right_curly;
  1045.     require(q->ntype == nJunction,    "genLoopBlk: not junction");
  1046.     require(q->jtype == aLoopBlk,    "genLoopBlk: not loop block");
  1047.  
  1048.     if ( q->visited ) return;
  1049.     q->visited = TRUE;
  1050.     if ( q->p2 == NULL )    /* only one alternative? */
  1051.     {
  1052.         if ( DemandLookahead )
  1053.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1054.             else gen1("look(%d);\n", max_k);
  1055.         gen("while ( ");
  1056.         if ( begin->parm!=NULL && begin->predparm ) _gen1("(%s) && ", begin->parm);
  1057.         genExpr(begin);
  1058.         /* if no predicates have been hoisted for this single alt (..)*
  1059.          * do so now
  1060.          */
  1061.         if ( ParseWithPredicates && begin->predicate==NULL )
  1062.         {
  1063.             Predicate *a = find_predicates((Node *)q->p1);
  1064.             if ( a!=NULL )
  1065.             {
  1066.                 _gen("&&");
  1067.                 genPredTree(a, q);
  1068.             }
  1069.         }
  1070.         _gen(" ) {\n");
  1071.         tabs++;
  1072.         TRANS(q->p1);
  1073.         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1074.         if ( DemandLookahead )
  1075.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1076.             else gen1("look(%d);\n", max_k);
  1077.         --tabs;
  1078.         gen("}\n");
  1079.         freeBlkFsets(q);
  1080.         q->visited = FALSE;
  1081.         return;
  1082.     }
  1083.     if (begin->parm!=NULL && begin->predparm) {_gen1("while (%s) {", begin->parm);}
  1084.     else gen("while ( 1 ) {\n");
  1085.     tabs++;
  1086.     f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
  1087.     set_free(f);
  1088.     freeBlkFsets(q);
  1089.  
  1090.     /* generate code for terminating loop (this is optional branch) */
  1091.     gen("else break;\n");        /* code for exiting loop "for sure" */
  1092.  
  1093.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1094.     if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1095.     --tabs;
  1096.     gen("}\n");
  1097.     q->visited = FALSE;
  1098. }
  1099.  
  1100. /*
  1101.  * Generate code for a loop blk of form:
  1102.  *
  1103.  *                          |---|
  1104.  *                         v   |
  1105.  *               --o-->o-->o-G-o-->o--
  1106.  *                   |           ^
  1107.  *                   v           |
  1108.  *                     o-----------o
  1109.  *
  1110.  * q->end points to the last node (far right) in the blk.  Note that q->end->jtype
  1111.  * must be 'EndBlk'.
  1112.  *
  1113.  * Generate code roughly of the following form:
  1114.  *
  1115.  *    do {
  1116.  *        ... code for alternatives ...
  1117.  *  } while ( First Set of aLoopBlk );
  1118.  *
  1119.  *    OR if > 1 alternative
  1120.  *
  1121.  *    do {
  1122.  *        ... code for alternatives ...
  1123.  *        else break;
  1124.  *  } while ( 1 );
  1125.  */
  1126. void
  1127. #ifdef __STDC__
  1128. genLoopBegin( Junction *q )
  1129. #else
  1130. genLoopBegin( q )
  1131. Junction *q;
  1132. #endif
  1133. {
  1134.     set f;
  1135.     int i;
  1136.     int max_k;
  1137.     require(q!=NULL,                "genLoopBegin: invalid node and/or rule");
  1138.     require(q->ntype == nJunction,    "genLoopBegin: not junction");
  1139.     require(q->jtype == aLoopBegin,    "genLoopBegin: not loop block");
  1140.     require(q->p2!=NULL,            "genLoopBegin: invalid Loop Graph");
  1141.  
  1142.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1143.  
  1144.     BLOCK_Preamble(q);
  1145.     BlkLevel++;
  1146.     f = First(q, 1, aLoopBegin, &max_k);
  1147.     genLoopBlk( q, (Junction *)q->p1, q, max_k );
  1148. #ifdef DUM
  1149. WAS:
  1150.     if ( LL_k>1 && !set_nil(q->fset[2]) )
  1151.         genLoopBlk( q, (Junction *)q->p1, q, max_k );
  1152.     else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
  1153. #endif
  1154.     for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
  1155.     for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
  1156.     --BlkLevel;
  1157.     BLOCK_Tail();
  1158.     set_free(f);
  1159.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1160. }
  1161.  
  1162. /*
  1163.  * Generate code for a loop blk of form:
  1164.  *
  1165.  *                      |---|
  1166.  *                     v   |
  1167.  *                   --o-G-o-->o--
  1168.  *
  1169.  * q->end points to the last node (far right) in the blk.  Note that q->end->jtype
  1170.  * must be 'EndBlk'.
  1171.  *
  1172.  * Generate code roughly of the following form:
  1173.  *
  1174.  *    do {
  1175.  *        ... code for alternatives ...
  1176.  *  } while ( First Set of aPlusBlk );
  1177.  *
  1178.  *    OR if > 1 alternative
  1179.  *
  1180.  *    do {
  1181.  *        ... code for alternatives ...
  1182.  *        else if not 1st time through, break;
  1183.  *  } while ( 1 );
  1184.  */
  1185. void
  1186. #ifdef __STDC__
  1187. genPlusBlk( Junction *q )
  1188. #else
  1189. genPlusBlk( q )
  1190. Junction *q;
  1191. #endif
  1192. {
  1193.     int max_k;
  1194.     set f;
  1195.     int need_right_curly;
  1196.     require(q!=NULL,                "genPlusBlk: invalid node and/or rule");
  1197.     require(q->ntype == nJunction,    "genPlusBlk: not junction");
  1198.     require(q->jtype == aPlusBlk,    "genPlusBlk: not Plus block");
  1199.     require(q->p2 != NULL,            "genPlusBlk: not a valid Plus block");
  1200.  
  1201.     if ( q->visited ) return;
  1202.     q->visited = TRUE;
  1203.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1204.     BLOCK_Preamble(q);
  1205.     BlkLevel++;
  1206.     /* if the ignore flag is set on the 2nd alt and that alt is empty,
  1207.      * then it is the implied optional alternative that we added for (...)+
  1208.      * and, hence, only 1 alt.
  1209.      */
  1210.     if ( ((Junction *)q->p2)->p2 == NULL &&
  1211.          ((Junction *)q->p2)->ignore )            /* only one alternative? */
  1212.     {
  1213.         Predicate *a=NULL;
  1214.         /* if the only alt has a semantic predicate, hoist it; must test before
  1215.          * entering loop.
  1216.          */
  1217.         if ( ParseWithPredicates )
  1218.         {
  1219.             a = find_predicates((Node *)q);
  1220.             if ( a!=NULL ) {
  1221.                 gen("if (");
  1222.                 genPredTree(a, q);
  1223.                 _gen(") {\n");
  1224.             }
  1225.         }
  1226.         gen("do {\n");
  1227.         tabs++;
  1228.         TRANS(q->p1);
  1229.         if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
  1230.         f = First(q, 1, aPlusBlk, &max_k);
  1231.         if ( DemandLookahead )
  1232.             if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1233.             else gen1("look(%d);\n", max_k);
  1234.         --tabs;
  1235.         gen("} while ( ");
  1236.         if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
  1237.         genExpr(q);
  1238. /*        if ( ParseWithPredicates && a!=NULL )
  1239.         {
  1240.             _gen("&&");
  1241.             genPredTree(a, q);
  1242.         }*/
  1243.         _gen(" );\n");
  1244.         if ( ParseWithPredicates && a!=NULL ) gen("}\n");
  1245.         --BlkLevel;
  1246.         BLOCK_Tail();
  1247.         q->visited = FALSE;
  1248.         freeBlkFsets(q);
  1249.         set_free(f);
  1250.         if (q->end->p1 != NULL) TRANS(q->end->p1);
  1251.         return;
  1252.     }
  1253.     gen("do {\n");
  1254.     tabs++;
  1255.     f = genBlk(q, aPlusBlk, &max_k, &need_right_curly);
  1256.     gen("else if ( zzcnt>1 ) break; /* implied exit branch */\n");/* code for exiting loop */
  1257.     tab();
  1258.     makeErrorClause(q,f,max_k);
  1259.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1260.     freeBlkFsets(q);
  1261.     gen("zzcnt++;");
  1262.     if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
  1263.     _gen("\n");
  1264.     if ( DemandLookahead )
  1265.         if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
  1266.         else gen1("look(%d);\n", max_k);
  1267.     --tabs;
  1268.     if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
  1269.     else gen("} while ( 1 );\n");
  1270.     --BlkLevel;
  1271.     BLOCK_Tail();
  1272.     q->visited = FALSE;
  1273.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1274. }
  1275.  
  1276. /*
  1277.  * Generate code for a sub blk of alternatives of form:
  1278.  *
  1279.  *                   --o-G1--o--
  1280.  *                     |     ^
  1281.  *                     v    /|
  1282.  *                     o-G2-o|
  1283.  *                     |     ^
  1284.  *                     v     |
  1285.  *                   ..........
  1286.  *                     |     ^
  1287.  *                     v    /
  1288.  *                     o-Gn-o
  1289.  *
  1290.  * q points to the 1st junction of blk (upper-left).
  1291.  * q->end points to the last node (far right) in the blk.  Note that q->end->jtype
  1292.  * must be 'EndBlk'.
  1293.  * The last node in every alt points to q->end.
  1294.  *
  1295.  * Generate code of the following form:
  1296.  *    if ( First(G1) ) {
  1297.  *        ...code for G1...
  1298.  *    }
  1299.  *    else if ( First(G2) ) {
  1300.  *        ...code for G2...
  1301.  *    }
  1302.  *    ...
  1303.  *    else {
  1304.  *        ...code for Gn...
  1305.  *    }
  1306.  */
  1307. void
  1308. #ifdef __STDC__
  1309. genSubBlk( Junction *q )
  1310. #else
  1311. genSubBlk( q )
  1312. Junction *q;
  1313. #endif
  1314. {
  1315.     int max_k;
  1316.     set f;
  1317.     int need_right_curly;
  1318.     require(q->ntype == nJunction,    "genSubBlk: not junction");
  1319.     require(q->jtype == aSubBlk,    "genSubBlk: not subblock");
  1320.  
  1321.     if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1322.     BLOCK_Preamble(q);
  1323.     BlkLevel++;
  1324.     f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
  1325.     if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
  1326.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1327.     freeBlkFsets(q);
  1328.     --BlkLevel;
  1329.     BLOCK_Tail();
  1330.  
  1331.     if ( q->guess )
  1332.     {
  1333.         gen("zzGUESS_DONE\n");
  1334.     }
  1335.  
  1336.     /* must duplicate if (alpha)?; one guesses (validates), the second pass matches */
  1337.     if ( q->guess && analysis_point(q)==q )
  1338.     {
  1339.         if ( GenLineInfo ) fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1340.         BLOCK_Preamble(q);
  1341.         BlkLevel++;
  1342.         f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
  1343.         if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
  1344.         { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1345.         freeBlkFsets(q);
  1346.         --BlkLevel;
  1347.         BLOCK_Tail();
  1348.     }
  1349.  
  1350.     if (q->end->p1 != NULL) TRANS(q->end->p1);
  1351. }
  1352.  
  1353. /*
  1354.  * Generate code for a rule.
  1355.  *
  1356.  *        rule--> o-->o-Alternatives-o-->o
  1357.  * Or,
  1358.  *        rule--> o-->o-Alternative-o-->o
  1359.  *
  1360.  * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction
  1361.  * (one alternative--no block), the last is EndRule.
  1362.  * The second to last is EndBlk if more than one alternative exists in the rule.
  1363.  *
  1364.  * To get to the init-action for a rule, we must bypass the RuleBlk,
  1365.  * and possible SubBlk.
  1366.  * Mark any init-action as generated so genBlk() does not regenerate it.
  1367.  */
  1368. void
  1369. #ifdef __STDC__
  1370. genRule( Junction *q )
  1371. #else
  1372. genRule( q )
  1373. Junction *q;
  1374. #endif
  1375. {
  1376.     int max_k;
  1377.     set follow, rk, f;
  1378.     ActionNode *a;
  1379.     RuleEntry *r;
  1380.     static int file = -1;
  1381.     int need_right_curly;
  1382.     require(q->ntype == nJunction,    "genRule: not junction");
  1383.     require(q->jtype == RuleBlk,    "genRule: not rule");
  1384.  
  1385.     r = (RuleEntry *) hash_get(Rname, q->rname);
  1386.     if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
  1387.     if ( q->file != file )        /* open new output file if need to */
  1388.     {
  1389.         if ( output != NULL ) fclose( output );
  1390.         output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
  1391.         require(output != NULL, "genRule: can't open output file");
  1392.  
  1393.         special_fopen_actions(OutMetaName(outname(FileStr[q->file])));
  1394.  
  1395.         if ( file == -1 ) genHdr1(q->file);
  1396.         else genHdr(q->file);
  1397.         file = q->file;
  1398.     }
  1399.     DumpFuncHeader(q,r);
  1400.     tabs++;
  1401.     if ( q->ret!=NULL )
  1402.     {
  1403.         if ( HasComma(q->ret) ) {gen1("struct _rv%d _retv;\n",r->rulenum);}
  1404.         else
  1405.         {
  1406.             tab();
  1407.             DumpType(q->ret, output);
  1408.             gen(" _retv;\n");
  1409.         }
  1410.     }
  1411.  
  1412.     if ( GenLineInfo )
  1413.     {
  1414.         fprintf(output, LineInfoFormatStr, q->line, FileStr[q->file]);
  1415.     }
  1416.  
  1417.     gen("zzRULE;\n");
  1418.     if ( GenCC && GenAST )
  1419.         gen("ASTBase **_astp, *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
  1420.     if ( GenCC ) genTokenPointers(q);
  1421.     if ( GenCC&&GenAST ) genASTPointers(q);
  1422.     if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
  1423.     if ( !GenCC ) gen("zzMake0;\n");
  1424.     if ( !GenCC ) gen("{\n");
  1425.  
  1426.     if ( has_guess_block_as_first_item((Junction *)q->p1) )
  1427.     {
  1428.         gen("zzGUESS_BLOCK\n");
  1429.     }
  1430.  
  1431.     /* L o o k  F o r  I n i t  A c t i o n */
  1432.     if ( ((Junction *)q->p1)->jtype == aSubBlk )
  1433.         a = findImmedAction( ((Junction *)q->p1)->p1 );
  1434.     else
  1435.         a = findImmedAction( q->p1 );    /* only one alternative in rule */
  1436.     if ( a!=NULL && !a->is_predicate )
  1437.     {
  1438.         dumpAction(a->action, output, tabs, a->file, a->line, 1);
  1439.         a->done = 1;    /* ignore action. We have already handled it */
  1440.     }
  1441.     if ( TraceGen )
  1442.         if ( GenCC ) {gen1("tracein(\"%s\");\n", q->rname);}
  1443.         else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
  1444.  
  1445.     BlkLevel++;
  1446.     q->visited = TRUE;                /* mark RULE as visited for FIRST/FOLLOW */
  1447.     f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly);
  1448.     if ( q->p1 != NULL )
  1449.         if ( ((Junction *)q->p1)->p2 != NULL )
  1450.             {tab(); makeErrorClause((Junction *)q->p1,f,max_k);}
  1451.     { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
  1452.     freeBlkFsets((Junction *)q->p1);
  1453.     q->visited = FALSE;
  1454.     --BlkLevel;
  1455.     if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
  1456.  
  1457.     if ( TraceGen )
  1458.         if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
  1459.         else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
  1460.  
  1461.     if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
  1462.     /* E r r o r  R e c o v e r y */
  1463.     NewSet();
  1464.     rk = empty;
  1465.     REACH(q->end, 1, &rk, follow);
  1466.     FillSet( follow );
  1467.     set_free( follow );
  1468.     _gen("fail:\n");
  1469.     if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
  1470.     if ( FoundGuessBlk )
  1471.            if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
  1472.         else gen("if ( guessing ) zzGUESS_FAIL;\n");
  1473.     if ( q->erraction!=NULL )
  1474.         dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
  1475.     if ( GenCC )
  1476.     {
  1477.         gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
  1478.              r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
  1479.     }
  1480.     else
  1481.     {
  1482.         gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
  1483.              r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
  1484.     }
  1485.     gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
  1486.  
  1487.     if ( TraceGen )
  1488.         if ( GenCC ) {gen1("traceout(\"%s\");\n", q->rname);}
  1489.         else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
  1490.  
  1491.     if ( q->ret!=NULL ) gen("return _retv;\n");
  1492.     if ( !GenCC ) gen("}\n");
  1493.     tabs--;
  1494.     gen("}\n");
  1495.     if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */
  1496.     else dumpAfterActions( output );
  1497. }
  1498.  
  1499. static void
  1500. #ifdef __STDC__
  1501. DumpFuncHeader( Junction *q, RuleEntry *r )
  1502. #else
  1503. DumpFuncHeader( q, r )
  1504. Junction *q;
  1505. RuleEntry *r;
  1506. #endif
  1507. {
  1508.     /* A N S I */
  1509.     _gen("\n");
  1510.     if ( q->ret!=NULL )
  1511.     {
  1512.         if ( HasComma(q->ret) )
  1513.         {
  1514.             if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
  1515.             else gen1("struct _rv%d\n",r->rulenum);
  1516.         }
  1517.         else
  1518.         {
  1519.             DumpType(q->ret, output);
  1520.             gen("\n");
  1521.         }
  1522.     }
  1523.     else
  1524.     {
  1525.         _gen("void\n");
  1526.     }
  1527.     if ( !GenCC ) _gen("#ifdef __STDC__\n");
  1528.     if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
  1529.     else gen2("%s::%s(", CurrentClassName, q->rname);
  1530.     if ( GenAST )
  1531.     {
  1532.         if ( GenCC ) {_gen("ASTBase **_root");}
  1533.         else _gen("AST**_root");
  1534.         if ( q->pdecl!=NULL ) _gen(",");
  1535.     }
  1536.     if ( q->pdecl!=NULL ) {_gen1("%s", q->pdecl);}
  1537.     else if ( !GenAST ) _gen("void");
  1538.     _gen(")\n");
  1539.  
  1540.     if ( GenCC ) {gen("{\n"); return;}
  1541.  
  1542.     /* K & R */
  1543.     gen("#else\n");
  1544. #ifdef DUM
  1545.     if ( q->ret!=NULL )
  1546.     {
  1547.         if ( HasComma(q->ret) ) {gen1("struct _rv%d\n",r->rulenum);}
  1548.         else
  1549.         {
  1550.             DumpType(q->ret, output);
  1551.             gen("\n");
  1552.         }
  1553.     }
  1554. #endif
  1555.     gen2("%s%s(", RulePrefix, q->rname);
  1556.     if ( GenAST )
  1557.     {
  1558.         _gen("_root");
  1559.         if ( q->pdecl!=NULL ) _gen(",");
  1560.     }
  1561.  
  1562.     DumpListOfParmNames( q->pdecl, output );
  1563.     gen(")\n");
  1564.     if ( GenAST ) gen("AST **_root;\n");
  1565.     DumpOldStyleParms( q->pdecl, output );
  1566.     gen("#endif\n");
  1567.     gen("{\n");
  1568. }
  1569.  
  1570. void
  1571. #ifdef __STDC__
  1572. genJunction( Junction *q )
  1573. #else
  1574. genJunction( q )
  1575. Junction *q;
  1576. #endif
  1577. {
  1578.     require(q->ntype == nJunction,    "genJunction: not junction");
  1579.     require(q->jtype == Generic,    "genJunction: not generic junction");
  1580.  
  1581.     if ( q->p1 != NULL ) TRANS(q->p1);
  1582.     if ( q->p2 != NULL ) TRANS(q->p2);
  1583. }
  1584.  
  1585. void
  1586. #ifdef __STDC__
  1587. genEndBlk( Junction *q )
  1588. #else
  1589. genEndBlk( q )
  1590. Junction *q;
  1591. #endif
  1592. {
  1593. }
  1594.  
  1595. void
  1596. #ifdef __STDC__
  1597. genEndRule( Junction *q )
  1598. #else
  1599. genEndRule( q )
  1600. Junction *q;
  1601. #endif
  1602. {
  1603. }
  1604.  
  1605. void
  1606. #ifdef __STDC__
  1607. genHdr( int file )
  1608. #else
  1609. genHdr( file )
  1610. int file;
  1611. #endif
  1612. {
  1613.     _gen("/*\n");
  1614.     _gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
  1615.     _gen(" *\n");
  1616.     _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  1617.     _gen(" * Purdue University Electrical Engineering\n");
  1618.     _gen(" * With AHPCRC, University of Minnesota\n");
  1619.     _gen1(" * ANTLR Version %s\n", Version);
  1620.     _gen(" */\n");
  1621.     _gen("#include <stdio.h>\n");
  1622.     _gen1("#define ANTLR_VERSION    %s\n", VersionDef);
  1623.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  1624.         _gen2("#define %s %s\n", DefaultParserName, ParserName);
  1625.        if ( strcmp(ParserName, DefaultParserName)!=0 )
  1626.         {_gen1("#include \"%s\"\n", RemapFileName);}
  1627.     if ( GenLineInfo ) _gen2(LineInfoFormatStr, 1, FileStr[file]);
  1628.     if ( GenCC ) {
  1629.         if ( UserTokenDefsFile != NULL )
  1630.             fprintf(output, "#include %s\n", UserTokenDefsFile);
  1631.         else
  1632.             fprintf(output, "#include \"%s\"\n", DefFileName);
  1633.     }
  1634.  
  1635.     if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
  1636.     if ( !GenCC && FoundGuessBlk )
  1637.     {
  1638.         _gen("#define ZZCAN_GUESS\n");
  1639.         _gen("#include <setjmp.h>\n");
  1640.     }
  1641.     if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
  1642.     if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
  1643.     if ( GenAST ) {
  1644.         if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
  1645.         else _gen("#include \"ast.h\"\n\n");
  1646.     }
  1647.     if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
  1648.     if ( !GenCC && LexGen ) {
  1649.         _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
  1650.     }
  1651.     /* ###WARNING: This will have to change when SetWordSize changes */
  1652.     if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  1653.     if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
  1654.     else {
  1655.         _gen1("#include \"%s\"\n", APARSER_H);
  1656.         _gen1("#include \"%s.h\"\n", CurrentClassName);
  1657.     }
  1658.     if ( !GenCC ) {
  1659.         if ( UserDefdTokens )
  1660.             {_gen1("#include %s\n", UserTokenDefsFile);}
  1661.         /* still need this one as it has the func prototypes */
  1662.         _gen1("#include \"%s\"\n", DefFileName);
  1663.     }
  1664.     /* still need this one as it defines the DLG interface */
  1665.     if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
  1666.     if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
  1667.     if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
  1668. }
  1669.  
  1670. void
  1671. #ifdef __STDC__
  1672. genHdr1( int file )
  1673. #else
  1674. genHdr1( file )
  1675. int file;
  1676. #endif
  1677. {
  1678.     ListNode *p;
  1679.  
  1680.     genHdr(file);
  1681.     if ( GenAST )
  1682.     {
  1683.         if ( !GenCC ) {
  1684.             _gen("#include \"ast.c\"\n");
  1685.             _gen("zzASTgvars\n\n");
  1686.         }
  1687.     }
  1688.     if ( !GenCC ) _gen("ANTLR_INFO\n");
  1689.     if ( BeforeActions != NULL )
  1690.     {
  1691.         for (p = BeforeActions->next; p!=NULL; p=p->next)
  1692.         {
  1693.             UserAction *ua = (UserAction *)p->elem;
  1694.             dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
  1695.         }
  1696.     }
  1697. }
  1698.  
  1699. void
  1700. #ifdef __STDC__
  1701. genStdPCCTSIncludeFile( FILE *f )
  1702. #else
  1703. genStdPCCTSIncludeFile( f )
  1704. FILE *f;
  1705. #endif
  1706. {
  1707.     fprintf(f,"#ifndef STDPCCTS_H\n");
  1708.     fprintf(f,"#define STDPCCTS_H\n");
  1709.     fprintf(f,"/*\n");
  1710.     fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);
  1711.     fprintf(f," *\n");
  1712.     fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994\n");
  1713.     fprintf(f," * Purdue University Electrical Engineering\n");
  1714.     fprintf(f," * With AHPCRC, University of Minnesota\n");
  1715.     fprintf(f," * ANTLR Version %s\n", Version);
  1716.     fprintf(f," */\n");
  1717.     fprintf(f,"#include <stdio.h>\n");
  1718.     fprintf(f,"#define ANTLR_VERSION    %s\n", VersionDef);
  1719.     if ( GenCC )
  1720.     {
  1721.         if ( UserDefdTokens )
  1722.             fprintf(f, "#include %s\n", UserTokenDefsFile);
  1723.         else {
  1724.             fprintf(f, "#include \"%s\"\n", DefFileName);
  1725.         }
  1726.  
  1727.         fprintf(f, "#include \"%s\"\n", ATOKEN_H);
  1728.  
  1729.         if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
  1730.  
  1731.         fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
  1732.  
  1733.         if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
  1734.         if ( GenAST ) {
  1735.             fprintf(f, "#include \"%s\"\n", ASTBASE_H);
  1736.         }
  1737.         fprintf(f,"#include \"%s\"\n", APARSER_H);
  1738.         fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
  1739.         if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
  1740.         fprintf(f, "#endif\n");
  1741.         return;
  1742.     }
  1743.  
  1744.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  1745.         fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
  1746.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  1747.         fprintf(f, "#include \"%s\"\n", RemapFileName);
  1748.     if ( UserTokenDefsFile != NULL )
  1749.        fprintf(f, "#include %s\n", UserTokenDefsFile);
  1750.     if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
  1751.     if ( FoundGuessBlk )
  1752.     {
  1753.         fprintf(f,"#define ZZCAN_GUESS\n");
  1754.         fprintf(f,"#include <setjmp.h>\n");
  1755.     }
  1756.     if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
  1757.     if ( GenAST ) fprintf(f,"#define GENAST\n");
  1758.     if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
  1759.     if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
  1760.     /* ###WARNING: This will have to change when SetWordSize changes */
  1761.     fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  1762.     fprintf(f,"#include \"antlr.h\"\n");
  1763.     if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
  1764.     if ( UserDefdTokens )
  1765.         fprintf(f, "#include %s\n", UserTokenDefsFile);
  1766.     /* still need this one as it has the func prototypes */
  1767.     fprintf(f, "#include \"%s\"\n", DefFileName);
  1768.     /* still need this one as it defines the DLG interface */
  1769.     fprintf(f,"#include \"dlgdef.h\"\n");
  1770.     /* don't need this one unless DLG is used */
  1771.     if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
  1772.     fprintf(f,"#endif\n");
  1773. }
  1774.  
  1775. /* dump action 's' to file 'output' starting at "local" tab 'tabs'
  1776.    Dump line information in front of action if GenLineInfo is set
  1777.    If file == -1 then GenLineInfo is ignored.
  1778.    The user may redefine the LineInfoFormatStr to his/her liking
  1779.    most compilers will like the default, however.
  1780.  
  1781.    June '93; changed so that empty lines are left alone so that
  1782.    line information is correct for the compiler/debuggers.
  1783. */
  1784. void
  1785. #ifdef __STDC__
  1786. dumpAction( char *s, FILE *output, int tabs, int file, int line, int final_newline )
  1787. #else
  1788. dumpAction( s, output, tabs, file, line, final_newline )
  1789. char *s;
  1790. FILE *output;
  1791. int tabs;
  1792. int file;
  1793. int line;
  1794. int final_newline;
  1795. #endif
  1796. {
  1797.     int inDQuote, inSQuote;
  1798.     require(s!=NULL,         "dumpAction: NULL action");
  1799.     require(output!=NULL,    eMsg1("dumpAction: output FILE is NULL for %s",s));
  1800.  
  1801.     if ( GenLineInfo && file != -1 )
  1802.     {
  1803.         fprintf(output, LineInfoFormatStr, line, FileStr[file]);
  1804.     }
  1805.     PastWhiteSpace( s );
  1806.     /* don't print a tab if first non-white char is a # (preprocessor command) */
  1807.     if ( *s!='#' ) {TAB;}
  1808.     inDQuote = inSQuote = FALSE;
  1809.     while ( *s != '\0' )
  1810.     {
  1811.         if ( *s == '\\' )
  1812.         {
  1813.             fputc( *s++, output ); /* Avoid '"' Case */
  1814.             if ( *s == '\0' ) return;
  1815.             if ( *s == '\'' ) fputc( *s++, output );
  1816.             if ( *s == '\"' ) fputc( *s++, output );
  1817.         }
  1818.         if ( *s == '\'' )
  1819.         {
  1820.             if ( !inDQuote ) inSQuote = !inSQuote;
  1821.         }
  1822.         if ( *s == '"' )
  1823.         {
  1824.             if ( !inSQuote ) inDQuote = !inDQuote;
  1825.         }
  1826.         if ( *s == '\n' )
  1827.         {
  1828.             fputc('\n', output);
  1829.             s++;
  1830.             PastWhiteSpace( s );
  1831.             if ( *s == '}' )
  1832.             {
  1833.                 --tabs;
  1834.                 TAB;
  1835.                 fputc( *s++, output );
  1836.                 continue;
  1837.             }
  1838.             if ( *s == '\0' ) return;
  1839.             if ( *s != '#' )    /* #define, #endif etc.. start at col 1 */
  1840.             {
  1841.                 TAB;
  1842.             }
  1843.         }
  1844.         if ( *s == '}' && !(inSQuote || inDQuote) )
  1845.         {
  1846.             --tabs;            /* Indent one fewer */
  1847.         }
  1848.         if ( *s == '{' && !(inSQuote || inDQuote) )
  1849.         {
  1850.             tabs++;            /* Indent one more */
  1851.         }
  1852.         fputc( *s, output );
  1853.         s++;
  1854.     }
  1855.     if ( final_newline ) fputc('\n', output);
  1856. }
  1857.  
  1858. static void
  1859. #ifdef __STDC__
  1860. dumpAfterActions( FILE *output )
  1861. #else
  1862. dumpAfterActions( output )
  1863. FILE *output;
  1864. #endif
  1865. {
  1866.     ListNode *p;
  1867.     require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
  1868.     if ( AfterActions != NULL )
  1869.     {
  1870.         for (p = AfterActions->next; p!=NULL; p=p->next)
  1871.         {
  1872.             UserAction *ua = (UserAction *)p->elem;
  1873.             dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
  1874.         }
  1875.     }
  1876.     fclose( output );
  1877. }
  1878.  
  1879. /*
  1880.  * Find the next action in the stream of execution.  Do not pass
  1881.  * junctions with more than one path leaving them.
  1882.  * Only pass generic junctions.
  1883.  *
  1884.  *    Scan forward while (generic junction with p2==NULL)
  1885.  *    If we stop on an action, return ptr to the action
  1886.  *    else return NULL;
  1887.  */
  1888. static ActionNode *
  1889. #ifdef __STDC__
  1890. findImmedAction( Node *q )
  1891. #else
  1892. findImmedAction( q )
  1893. Node *q;
  1894. #endif
  1895. {
  1896.     Junction *j;
  1897.     require(q!=NULL, "findImmedAction: NULL node");
  1898.     require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
  1899.     
  1900.     while ( q->ntype == nJunction )
  1901.     {
  1902.         j = (Junction *)q;
  1903.         if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
  1904.         q = j->p1;
  1905.         if ( q == NULL ) return NULL;
  1906.     }
  1907.     if ( q->ntype == nAction ) return (ActionNode *)q;
  1908.     return NULL;
  1909. }
  1910.  
  1911. static void
  1912. #ifdef __STDC__
  1913. dumpRetValAssign( char *retval, char *ret_def )
  1914. #else
  1915. dumpRetValAssign( retval, ret_def )
  1916. char *retval;
  1917. char *ret_def;
  1918. #endif
  1919. {
  1920.     char *q = ret_def;
  1921.     
  1922.     tab();
  1923.     while ( *retval != '\0' )
  1924.     {
  1925.         while ( isspace((*retval)) ) retval++;
  1926.         while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
  1927.         fprintf(output, " = _trv.");
  1928.         
  1929.         DumpNextNameInDef(&q, output);
  1930.         fputc(';', output); fputc(' ', output);
  1931.         if ( *retval == ',' ) retval++;
  1932.     }
  1933. }
  1934.  
  1935. /* This function computes the set of tokens that can possibly be seen k
  1936.  * tokens in the future from point j
  1937.  */
  1938. static set
  1939. #ifdef __STDC__
  1940. ComputeErrorSet( Junction *j, int k )
  1941. #else
  1942. ComputeErrorSet( j, k )
  1943. Junction *j;
  1944. int k;
  1945. #endif
  1946. {
  1947.     Junction *alt1;
  1948.     set a, rk, f;
  1949.     require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
  1950.  
  1951.     f = rk = empty;
  1952.     for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
  1953.     {
  1954.         REACH(alt1->p1, k, &rk, a);
  1955.         require(set_nil(rk), "ComputeErrorSet: rk != nil");
  1956.         set_free(rk);
  1957.         set_orin(&f, a);
  1958.         set_free(a);
  1959.     }
  1960.     return f;
  1961. }
  1962.  
  1963. static void
  1964. #ifdef __STDC__
  1965. makeErrorClause( Junction *q, set f, int max_k )
  1966. #else
  1967. makeErrorClause( q, f, max_k )
  1968. Junction *q;
  1969. set f;
  1970. int max_k;
  1971. #endif
  1972. {
  1973.     if ( max_k == 1 )
  1974.     {
  1975.         if ( GenCC ) {_gen1("else {FAIL(1,err%d", DefErrSet(&f,1));}
  1976.         else _gen1("else {zzFAIL(1,zzerr%d", DefErrSet(&f,1))
  1977.         set_free(f);
  1978.     }
  1979.     else
  1980.     {
  1981.         int i;
  1982.         set_free(f);
  1983.         if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
  1984.         else _gen1("else {zzFAIL(%d", max_k);
  1985.         for (i=1; i<=max_k; i++)
  1986.         {
  1987.             f = ComputeErrorSet(q, i);
  1988.             if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1 ));}
  1989.             else _gen1(",zzerr%d", DefErrSet( &f, 1 ));
  1990.             
  1991.             set_free(f);
  1992.         }
  1993.     }
  1994.     _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
  1995. }
  1996.